home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / PCASM2.ZIP / CHAP8.DOC < prev    next >
Text File  |  1990-06-21  |  31KB  |  736 lines

  1.  
  2.  
  3.  
  4.                                                                             56
  5.  
  6.                               CHAPTER 8 - SHIFT AND ROTATE
  7.  
  8.  
  9.              There are seven instructions that move the individual bits of a
  10.              byte or word either left or right. Each instruction works
  11.              slightly differently. We'll make a standard program and then
  12.              substitute each instruction into that program.
  13.  
  14.  
  15.              SAL - SHL
  16.  
  17.              The instructions SHL (shift logical left) and SAL (shift
  18.              arithmetic left) are exactly the same. They have the same machine
  19.              code. They shift each bit to the left. How far? That depends.
  20.              There are two (and only two) forms of this instruction. All other
  21.              shift and rotate instructions have these two (and only these two)
  22.              forms as well. The first form is:
  23.  
  24.                  shl  al, 1
  25.  
  26.              Which shifts each bit to the left one bit. The number MUST be 1.
  27.              No other number is possible. The other form is:
  28.  
  29.                  shl  al, cl
  30.  
  31.              shifts the bits in AL to the left by the number in CL. If CL = 3,
  32.              it shifts left by 3. If CL = 7, it shifts left by 7. The count
  33.              register MUST be CL (not CX). The bits on the left are shifted
  34.              out of the register into the bit bucket, and zeros are inserted
  35.              on the right. The easy way to understand this is to fire up the
  36.              standard program. Remember, from now on we always use
  37.              template.asm.
  38.  
  39.              ;sal.asm
  40.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  41.                     mov   ax_byte, 0A3h       ; half reg, low reg binary 
  42.                     mov   bx_byte, 0A4h       ; half reg, low reg hex 
  43.                     mov   cx_byte, 0A1h       ; half reg, low reg signed 
  44.                     mov   dx_byte, 0A2h       ; half reg, low reg unsigned 
  45.                     lea   ax, ax_byte 
  46.                     call  set_reg_style 
  47.               
  48.                     mov   ax, 0               ; clear registers
  49.                     mov   bx, 0 
  50.                     mov   cx, 0 
  51.                     mov   dx, 0 
  52.                     mov   di, 0 
  53.                     mov   bp, 0 
  54.                     call  show_regs 
  55.               
  56.              outer_loop: 
  57.                     call  get_hex_byte   ; get number and put in registers 
  58.                     mov   bl, al 
  59.                     mov   cl, al 
  60.  
  61.              ______________________
  62.  
  63.              The PC Assembler Tutor - Copyright (C) 1989 Chuck Nelson
  64.  
  65.  
  66.  
  67.  
  68.              Chapter 8 - Shift and Rotate                                   57
  69.              ____________________________
  70.  
  71.                     mov   dl, al 
  72.                     mov   si, 8         ; 8 iterations of the loop
  73.                     and   al, al        ; set the flags
  74.                     call  show_regs_and_wait 
  75.              shift_loop: 
  76.                     sal   al, 1 
  77.                     sal   bl, 1 
  78.                     sal   cl, 1 
  79.                     sal   dl, 1 
  80.                     call  show_regs_and_wait 
  81.                     dec   si 
  82.                     jnz   shift_loop 
  83.                     jmp   outer_loop 
  84.               
  85.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  86.  
  87.              This standard program is with bytes, not words. This is because
  88.              if we had used words we would have performed 16 individual shifts
  89.              and that would have been time consuming and boring. First we set
  90.              the style to half registers. Notice that one is binary, one is
  91.              hex, one is signed and one is unsigned. That covers all bases.
  92.              All the registers are then cleared. It would be nice to use the
  93.              loop instruction, but CX is committed, so we make our own loop
  94.              instruction. We move 8 into SI. The loop instructions are:
  95.  
  96.                  dec  si
  97.                  jnz  shift_loop
  98.  
  99.              DEC decrements a register or a variable by 1. Its counterpart INC
  100.              increments a register or variable by 1. JNZ (jump if not zero)
  101.              jumps to 'shift_loop' if SI is not zero.
  102.  
  103.              We get a hex byte in AL and put the same byte in BL, CL, and DL.
  104.              This way we will be able to see what is happening in binary, hex,
  105.              signed and unsigned. Before starting, we have:
  106.  
  107.                  and  al, al
  108.  
  109.              This is there to set the flags correctly before starting. All
  110.              four are shifted left one bit each time, and then we look at the
  111.              result.
  112.  
  113.              Assemble, link and run it. Enter the number 7. In binary, that is
  114.              (0000 0111). Take a look at the flags before starting. It is a
  115.              positive number so SF shows '+'. ZF is not set. PF shows 'O'. O
  116.              stands for odd. Every time you perform an arithmetic or logical
  117.              operation, the 8086 checks parity. Parity is whether the number
  118.              contains an even or odd number of 1 bits. This contains 3 1 bits,
  119.              so the parity is odd. The possible settings are 'E' for even and
  120.              'O' for odd.{1} SAL checks for parity (though some of the other
  121.              instructions don't).  Now press ENTER. It will shift left 1 and
  122.              you will have (0000 1110). What does the unsigned number say now?
  123.              14. Press ENTER again. (0001 1100) What does the unsigned number
  124.              say? 28. Again (0011 1000) 56. Again (0111 0000) 112. Notice that
  125.              ____________________
  126.  
  127.                 1 This is for use by communications programs.
  128.  
  129.  
  130.  
  131.  
  132.              The PC Assembler Tutor                                         58
  133.              ______________________
  134.  
  135.              the signed number reads +112. Look at the CF and OF. They are
  136.              both cleared. Things are going to change now. Press ENTER again.
  137.              (1110 0000). SF is now '-'. OF, the overflow flag is set because
  138.              you changed the number from positive to negative (from +112 to
  139.              -32). What is the unsigned number now? 224. CF is cleared. PF is
  140.              '0'. Shift again. (1100 0000) OF is cleared because you didn't
  141.              change signs. (Remember, the leftmost bit is the sign bit for a
  142.              signed number). PF is now 'E' because you have two 1 bits, and
  143.              two is even. CF is set because you shifted a 1 bit off the left
  144.              end. Keep pressing ENTER and watch SF, OF, CF, and PF.
  145.  
  146.              Let's look at the unsigned numbers we had until we started
  147.              shifting 1 bits off the left end. We started with 7, then had 14,
  148.              28, 56, 112, 224. This instruction is multiplying by 2. That's
  149.              right, and it is MUCH faster than multiplication (about 50 times
  150.              faster). Far and away the fastest way to multiply a register by
  151.              2, 4 or 8 is to use sal.
  152.  
  153.                  ; by 2              ;by 4               ; by 8
  154.                  sal  di,1           sal  di, 1          sal  di, 1
  155.                                      sal  di, 1          sal  di, 1
  156.                                                          sal  di, 1
  157.  
  158.              For a register, it is faster to use a series of 1 shifts than to
  159.              load cl. For a variable in memory, anything over 1 shift is
  160.              faster if you load cl.
  161.  
  162.              Do a few more numbers to see what is happening both with the
  163.              number and the flags. CF always signals when a 1 bit has been
  164.              shifted off the end.
  165.  
  166.  
  167.              SAR and SHR
  168.  
  169.              Unlike the left shift instruction, there are two completely
  170.              different right shift instructions. SHR (shift logical right)
  171.              shifts the bits to the right, setting CF if a 1 bit is pushed off
  172.              the right end. It puts 0s in the leftmost bit. Make a copy of
  173.              SAL.ASM and replace the four instructions:
  174.  
  175.                     sal   al, 1 
  176.                     sal   bl, 1 
  177.                     sal   cl, 1 
  178.                     sal   dl, 1 
  179.  
  180.              with SHR. We'll call the new program SHR.ASM. Run this one too.
  181.              Instead of 7, use E0h (1110 0000) which is 224d. The first time
  182.              you shift (0111 0000) the OF flag will be set because the sign
  183.              changed. Keep shifting, noting the flags and the unsigned number.
  184.              This time we have 224, 112, 56, 28, 14, 7, 3, 1. It is dividing
  185.              by two and is once again MUCH faster than division. For a single
  186.              shift, the remainder is in CF. For a shift of more than one bit,
  187.              you lose the remainder, but there is a way around this which we
  188.              will discuss in a moment. Do some more numbers till you are
  189.              comfortable with the flags and the operation.
  190.  
  191.              If you want to divide by 16, you will shift right four times, so
  192.  
  193.  
  194.  
  195.  
  196.              Chapter 8 - Shift and Rotate                                   59
  197.              ____________________________
  198.  
  199.              you'll lose those 4 bits. But those bits are exactly the value of
  200.              the remainder. All we need to do is:
  201.  
  202.                  mov  dx, ax    ; copy of number to dx
  203.                  and  dx, 0000000000001111b ; remainder in dx
  204.                  mov  cl, 4     ; shift right 4 bits
  205.                  shr  ax, cl    ; quotient in ax
  206.  
  207.              Using a mask, we keep only the right four bits, which is the
  208.              remainder.
  209.  
  210.  
  211.              SAR
  212.  
  213.              SAR (shift arithmetic right) is different. It shifts right like
  214.              SHR, but the leftmost bit always stays the same. This will make
  215.              more sense when you run the program. Make another copy, call it
  216.              SAR.ASM, and change the four instructions to SAR. The flags
  217.              operate the same as for SHR and SHL. The overflow flag will never
  218.              change since the left bit will always stay the same. 
  219.  
  220.              First enter 74h (+116). We will be looking at the signed numbers
  221.              only. Copy down the signed numbers as you go along. They should
  222.              be: 116, 58, 29, 14, 7, 3, 1, 0, 0. Now try 8Ch (-116). The
  223.              numbers you should get are: -116, -58, -29, -15, -8, -4, -2, -1,
  224.              -1. They started out the same, then they got off by one. The
  225.              negative numbers are one too negative. Try  39h (+57). The
  226.              numbers here are: 57, 28, 14, 7, 3, 1, 0, 0, 0. Just as it should
  227.              be for division by 2. Now try C7 (-57). Here the numbers are:
  228.              -57, -29, -15, -8, -4, -2, -1, -1, -1. This time it went screwy
  229.              right off the bat. Once again, the negative numbers are one too
  230.              negative. 
  231.  
  232.              SAR is an instruction for doing signed division by 2 (sort of).
  233.              It is, however, an incomplete instruction. The rule for SAR is:
  234.              SAR gives the correct answer if the number is positive. It gives
  235.              the correct answer if the number is negative and the remainder is
  236.              zero. If the number is negative but there is a remainder, then
  237.              the answer is one too negative. The reason for this is a little
  238.              complex, but we need to add some code if we want to do signed
  239.              division.{2} For SHR, the remainder part was optional. Here it is
  240.              not. We need to know whether the remainder is zero or not. For
  241.              this example we will do a word shift left by 6. That's dividing
  242.              by 64.
  243.  
  244.                  remainder_mask dw   002Fh     ; 63
  245.  
  246.                  call get_signed          ; number in ax
  247.                  mov  bx, ax              ; copy in bx
  248.                  and  bx, remainder_mask  ; the remainder
  249.                  mov  cl,6                ; shift right 6 bits
  250.                  sar  ax, cl
  251.                  jns  continue            ; is it positive?
  252.              ____________________
  253.  
  254.                 2 Both the code and the reasons will be explained (but not
  255.              proved) in the summary.
  256.  
  257.  
  258.  
  259.  
  260.              The PC Assembler Tutor                                         60
  261.              ______________________
  262.  
  263.                  and  bx, bx              ; is the remainder zero?
  264.                  jz   continue
  265.                  inc  ax
  266.              continue:
  267.  
  268.              We get the remainder, then shift right 6 bits. Upon finishing
  269.              SAR, the sign flag will be set correctly. Here is yet another
  270.              jump. This one is JNS (jump on not sign) jumps if the sign flag
  271.              is NOT set, that is if the number is positive. If it is positive,
  272.              then everything is ok so we skip ahead. If the number is
  273.              negative, then we check to see if there was a remainder. If there
  274.              wasn't, everything is ok, so we go ahead. If there was a
  275.              remainder, then we INC (add 1) ax. 
  276.  
  277.              Is the remainder correct? If the number was positive, the
  278.              remainder is correct, but if the number was negative, then we
  279.              need to do one more thing. After INC, but before 'continue' we
  280.              have a SUB instruction:
  281.  
  282.                       inc  ax
  283.                       sub  bx, 64    ; correct the remainder
  284.                  continue:
  285.  
  286.              Why that is the correct number will be explained in the summary.
  287.              What a lot of work when we could simply write:
  288.  
  289.                  mov  cx, 64
  290.                  call get_signed
  291.                  cwd                 ; sign extend
  292.                  idiv cx             ; signed division
  293.  
  294.              Is there any advantage to this instruction? Not really. Remember
  295.              that the more you shift, the longer it takes. If you shift 2,
  296.              then it's about 1/3 faster than division. If you shift 14, then
  297.              it is only 15% faster than division. Considering that even a slow
  298.              PC can do 25000 divisions a second, you must be in serious need
  299.              of speed to use this. In any case, you will never or almost never
  300.              use SAR for signed division, while you will find lots of
  301.              opportunity to use SHR and SHL for unsigned multiplication and
  302.              division.
  303.  
  304.  
  305.              ROR and ROL
  306.  
  307.              ROR (rotate right) and ROL (rotate left) rotate the bits around
  308.              the register. We will just do one program since they operate the
  309.              same way, only in opposite directions. Make another copy of
  310.              SAL.ASM and put in ROR in the appropriate spots. 
  311.  
  312.              Enter a number. This time you will notice that the bits, rather
  313.              than dissapearing off the end, reappear on the other side. They
  314.              rotate around the register. The only flags that are defined are
  315.              OF and CF. OF is set if the high bit changes, and CF is set if a
  316.              1 bit moves off the end of the register to the other side. Do a
  317.              few more, and we'll go on to the last two instructions.
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.              Chapter 8 - Shift and Rotate                                   61
  325.              ____________________________
  326.  
  327.              RCR and RCL
  328.  
  329.              RCR (rotate through carry right) and RCL (rotate through carry
  330.              left) rotate the same as the above instructions except that the
  331.              carry flag is involved. Rotating right, the low bit moves to CF,
  332.              the carry flag and CF moves to the high bit. Rotating left, the
  333.              high bit moves to CF and CF moves to the low bit. There are 9
  334.              bits (or 17 bits for a word) involved in the rotation. Make yet
  335.              another copy of the program, and change those 4 instructions to
  336.              RCR. Also, since we have 9 bits instead of 8, change the loop
  337.              count to 9 from 8:
  338.  
  339.                  mov  si, 9
  340.  
  341.              Enter a number and watch it move. Before you start moving, look
  342.              at CF and see if there is anything in it. There are only two
  343.              flags defined, OF and CF. Obviously, CF is set if there is
  344.              something in it. OF is wierd. In RCL (the opposite instruction to
  345.              the one we are using), OF operates normally, signalling a change
  346.              in the top (sign) bit. In RCR, OF signals a change in CF. Why? I
  347.              don't have the slightest idea. You really have no need for the OF
  348.              flag anyways, so this is unimportant.
  349.  
  350.  
  351.              Well, those are the seven instructions, but what can you do with
  352.              them besides multiply and divide?
  353.  
  354.              First, you can work with multiple bit data. The 8087 has a word
  355.              length register called the status register.  Looking at the upper
  356.              byte:
  357.  
  358.                  15 14 13 12 11 10  9  8
  359.                         X  X  X
  360.  
  361.              bits 11, 12 and 13 contain a number from 0 to 7. The data in this
  362.              register is not directly accessable. You need to move the
  363.              register into memory, then into an 8086 register. If you want to
  364.              find what this number is, what do you do?
  365.  
  366.                  mov  bx, status_register_data
  367.                  mov  cl, 3
  368.                  ror  bx, cl
  369.                  and  bh, 00000111b
  370.  
  371.              we rotate right 3 and then mask off everything else. The number
  372.              is now in BH. We could have used SHR if we wanted. Another 8087
  373.              register is the control register. In the upper byte it has:
  374.  
  375.                  15 14 13 12 11 10  9  8
  376.                               X  X
  377.  
  378.              a number from 0 to 3 in bits 10 and 11. If we want the
  379.              information, we do the same thing:
  380.  
  381.                  mov  bx, control_register_data
  382.                  mov  cl, 2
  383.                  ror  bx, cl
  384.  
  385.  
  386.  
  387.  
  388.              The PC Assembler Tutor                                         62
  389.              ______________________
  390.  
  391.                  and  bh, 00000011b
  392.  
  393.              and the number is in BH. 
  394.  
  395.              You are now going to write a program that inputs an unsigned
  396.              number and prints out its hex representation. Here it is:
  397.  
  398.  
  399.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  400.                     mov   ax_byte, 0A5h        ; half regs, right ascii 
  401.                     mov   bx_byte, 4           ; hex 
  402.                     mov   dx_byte, 4           ; hex 
  403.                     lea   ax, ax_byte 
  404.                     call  set_reg_style 
  405.                     call  show_regs 
  406.               
  407.              outer_loop: 
  408.                     call  get_unsigned 
  409.                     mov   bx, ax 
  410.                     mov   dx, ax 
  411.                     mov   cx, 4 
  412.              inner_loop: 
  413.                     push  cx                  ; save cx 
  414.                     mov   cl, 4 
  415.                     rol   bx, cl              ; rotate left 1/2 byte 
  416.                     mov   al, bl              ; copy to al 
  417.                     and   al, 0Fh             ; mask off upper 1/2 byte 
  418.                     cmp   al, 10              ; < 10, 0 - 9 ;  > 9  A - F 
  419.                     jae   use_letters 
  420.                     add   al, '0'             ; change to ascii 
  421.                     jmp   print_it 
  422.              use_letters: 
  423.                     add   al, 'A' - 10         ;  10 = 'A' 
  424.              print_it: 
  425.                     call  print_ascii_byte 
  426.                     call  show_regs_and_wait 
  427.                     pop   cx 
  428.                     loop  inner_loop 
  429.                     jmp   outer_loop 
  430.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  431.  
  432.              AL will be shown in ascii while BX and DX will be in hex. We save
  433.              the original number in DX. Since the first thing we want to print
  434.              is the left hex character, we rotate left, not right. We move the
  435.              low byte to AL, mask off everything but the low hex number and
  436.              then convert to an ascii character. If it is 0 - 9, we add '0'
  437.              (the character, not the number). If it is > 9, we add "'A' - 10"
  438.              and get a letter (if the number is 10, we get 'A'). JAE means
  439.              jump if above or equal, and is an unsigned comparison.{3}
  440.  
  441.  
  442.              ____________________
  443.  
  444.                 3 You are getting innundated with conditional jump
  445.              instructions. Don't worry. As long as you understand each one
  446.              when you run across it, you don't have to remember it. All jump
  447.              instructions will be covered soon.
  448.  
  449.  
  450.  
  451.  
  452.              Chapter 8 - Shift and Rotate                                   63
  453.              ____________________________
  454.  
  455.              Finally, we print the ascii character that is in AL.{4}
  456.  
  457.              Another thing to notice is that just inside the loop we push CX.
  458.              That is because we use CL for the ROL instruction. It is then
  459.              POPped just before the loop instruction. This is typical. CX is
  460.              the only register that can be used for counting in indexed
  461.              instructions. It is common for indexing instructions to be
  462.              nested, so you temporarily store the old value of CX while you
  463.              are using CX for something different.
  464.  
  465.                  push cx        ; typical code for a shift
  466.                  mov  cl, 7
  467.                  shr  si, cl
  468.                  pop  cx
  469.  
  470.  
  471.              Finally, let's multiply large numbers by 2. Here's the code:
  472.  
  473.              ; + + + + + + + + + + + + + + + START DATA BELOW THIS LINE 
  474.              byte1  db    ? 
  475.              byte2  db    ? 
  476.              byte3  db    ? 
  477.              byte4  db    ? 
  478.              error_message  db  "Result is too large.", 0
  479.              ; + + + + + + + + + + + + + + + END DATA ABOVE THIS LINE 
  480.  
  481.              ; + + + + + + + + + + + + + + + START CODE BELOW THIS LINE 
  482.              outer_loop: 
  483.                     lea   ax, byte1           ; get 4 byte number 
  484.                     call  get_unsigned_4byte 
  485.               
  486.                     shl   byte1, 1 
  487.                     rcl   byte2, 1 
  488.                     rcl   byte3, 1 
  489.                     rcl   byte4, 1 
  490.                     jnc   go_on
  491.                     lea   ax, error_message
  492.                     call  print_string
  493.              go_on:
  494.                     lea   ax, byte1 
  495.                     call  print_unsigned_4byte 
  496.                     jmp   outer_loop 
  497.              ; + + + + + + + + + + + + + + + END CODE ABOVE THIS LINE 
  498.  
  499.              This will require some explaination. Get_unsigned_4byte gets a
  500.              number from 1 to four billion. We put it in memory. Normally, the
  501.              following instructions would be done word by word. We are doing
  502.              them byte by byte so you can see the mechanics of the situation.
  503.              The low byte is shifted left 1 bit. This doubles it, but may
  504.              shift a 1 bit from the high bit into CF. If it does, then it will
  505.              be present when we rotate byte2. That moves CF into the low bit
  506.              and moves the high bit into CF. We do it again. And again. If
  507.              there is an unsigned overflow, it will be signalled by CF being
  508.              ____________________
  509.  
  510.                 4 Any subroutine in ASMHELP.OBJ that involves a one byte input
  511.              or output has the data in AL.
  512.  
  513.  
  514.  
  515.  
  516.              The PC Assembler Tutor                                         64
  517.              ______________________
  518.  
  519.              set after:
  520.  
  521.                  rcl  byte4, 1
  522.  
  523.              JNC (jump on not carry) will skip the error message if everything
  524.              is ok. Print_string prints a zero terminated string, that is a C
  525.              string which is terminated by the number (not the character) 0.
  526.              Finally, we print the number.
  527.  
  528.              A word about large numbers in ASMHELP.OBJ. It is assumed that you
  529.              would like to use commas if you could. Any data type over 1 word
  530.              long allows commas. The following are considered the same by
  531.              ASMHELP.OBJ in its input routines:
  532.  
  533.                  23546787
  534.                  2,3,5,4,6,7,8,7
  535.                  23,,5,46,,78,7
  536.                  23,546787
  537.                  23,546,787
  538.  
  539.              It always prints commas correctly in the print routines.
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.              Chapter 8 - Shift and Rotate                                   65
  581.              ____________________________
  582.  
  583.                                           SUMMARY
  584.  
  585.              All shift and rotate instructions operate on either a register or
  586.              on memory. They can be either 1 bit shifts:
  587.  
  588.                  sal  cx, 1
  589.                  ror  variable1, 1
  590.                  shr  bl, 1
  591.  
  592.              or shifts indexed by CL (it must be CL):
  593.  
  594.                  rcl  variable2, cl
  595.                  sar  si, cl
  596.                  rol  ah, cl
  597.  
  598.  
  599.  
  600.              SHL and SAL
  601.  
  602.                  SHL (shift logical left) and SAL (shift arithmetic left) are
  603.                  exactly the same instruction. They move bits left. 0s are
  604.                  placed in the low bit. Bits are shoved off the register (or
  605.                  memory data) on the left side, and CF indicates whether the
  606.                  last bit shoved was a 1 or a 0. It is used for multiplying
  607.                  an unsigned number by powers of 2.
  608.  
  609.  
  610.              SHR
  611.  
  612.                  SHR (shift logical right) does the same thing as SHL but in
  613.                  the opposite direction. Bits are shifted right. 0s are
  614.                  placed in the high bit. Bits are shoved off the register (or
  615.                  memory data) on the right side and CF indicates whether the
  616.                  last bit shoved off was a 0 or a 1. It is used for dividing
  617.                  an unsigned number by powers of 2.
  618.  
  619.  
  620.              SAR
  621.  
  622.                  SAR (shift arithmetic right) shifts bits right. The high
  623.                  (sign) bit stays the same throughout the operation. Bits are
  624.                  shoved off the register (or memory data) on the right side.
  625.                  CF indicates whether the last bit shoved off was a 1 or a 0.
  626.                  It is used (with difficulty) for dividing a signed number by
  627.                  powers of 2.
  628.  
  629.  
  630.              ROR and ROL
  631.  
  632.                  ROR (rotate right) and ROL (rotate left) rotate the bits of
  633.                  a register (or memory data) right and left respectively. The
  634.                  bit which is shoved off one end is moved to the other end.
  635.                  CF indicates whether the last bit moved from one end to the
  636.                  other was a 1 or a 0.
  637.  
  638.              RCR and RCL
  639.  
  640.  
  641.  
  642.  
  643.  
  644.              The PC Assembler Tutor                                         66
  645.              ______________________
  646.  
  647.                  RCR (rotate through carry right) and RCL (rotate through
  648.                  carry left) rotate the bits of a register (or of memory
  649.                  data) right and left respectively. The bit which is shoved
  650.                  off the register (or data) is placed in CF and the old CF is
  651.                  placed on the other side of the register (or data).
  652.  
  653.  
  654.              INC
  655.                  INC increments a register or a variable by 1.
  656.  
  657.                       inc  ax
  658.                       inc variable1
  659.  
  660.              DEC
  661.                  DEC decrements a register or a variable by 1.
  662.  
  663.                       dec  ax
  664.                       dec  variable1
  665.  
  666.  
  667.  
  668.              The following is fairly technical. It is only for those willing
  669.              to wade their way through a turgid explaination. If you don't
  670.              understand it, forget it.
  671.  
  672.              CODE FOR SHL
  673.  
  674.              If you are shifting an UNSIGNED number right by 'X' bits, it is
  675.              the same as dividing by (2 ** X)  1 bit = (2**1 = 2), 2 bits =
  676.              (2**2 = 4), 7 bits = (2**7 = 128). This is the same as dividing
  677.              by a number which is all 0s except the Xth bit which is 1 (for 0
  678.              we have 0000 0001, for 1 we have 0000 0010, for 3 we have 0000
  679.              1000, for 7 we have 1000 0000). The remainder mask will be this
  680.              number minus 1 (for 0 we have 0000 0000, for 1 we have 0000 0001,
  681.              for 3 we have 0000 0111, for 7 we have 0111 1111). 
  682.  
  683.  
  684.              CODE FOR SAR
  685.  
  686.              The order of numbers is important for SAR. If you start with 0
  687.              and add 1 each time, the actual sequence of signed numbers that
  688.              you get (from the bottom up) is:
  689.  
  690.  
  691.                  -1
  692.                  -2
  693.                   .
  694.                   .
  695.                  -32767
  696.                  -32768
  697.                  +32767
  698.                  +32766
  699.                   .
  700.                   .
  701.                   3
  702.                   2
  703.                   1
  704.                   0
  705.  
  706.  
  707.  
  708.              Chapter 8 - Shift and Rotate                                   67
  709.              ____________________________
  710.  
  711.  
  712.              The positive numbers are increasing in absolute value while the
  713.              negative numbers are decreasing in absolute value. If you divide
  714.              by shifting and there is no remainder, then the quotient is
  715.              exact. If there is a remainder, the quotient will truncate
  716.              towards 0 IN THE ABOVE DIAGRAM. This means that positive numbers
  717.              will truncate down, while the negative numbers will truncate
  718.              towards -32768, and will be one too negative. 
  719.  
  720.              If the number was positive, the remainder will be positive and
  721.              will be exactly the same as for SHR. If the number was negative,
  722.              then things are more complicated. We'll take division by 32 as an
  723.              example. If we divide by 32 (0010 0000) the remainder mask will
  724.              be 31 (0001 1111). If the number is negative, then what we get
  725.              when we AND the mask:
  726.  
  727.                  and  ax, 00011111b
  728.  
  729.              is not the remainder but (remainder + 32). In order to get the
  730.              actual negative remainder, we need to subtract 32. This gives us
  731.              (remainder + 32 - 32). 
  732.  
  733.                  remainder mask = divisor - 1
  734.                  negative remainder correction = NEG divisor.
  735.  
  736.